/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Simulator;

/**
 *The Jump class will be called from the Simulator's Control calss and is used to process jumps.
 * @author khhill
 */
public class Jump {

    
    
    
                   /**
* The Equal function will be called when the function bits are 000.  The function will first get an interger value from the bit code in the operand 
     * field from the instruction. 
     * Then, the function will find the value in that memory location and use that as the operand value.  
     * The function then pops an item in the test stack.  If is 0, it will jump to the desired location.<p>
* <p>
* <b>Change Log:</b><br>
* None<br>
* <p>
* <b>Error Conditions Tested:</b><br>
* 169 - Value at memory not defined. <br>
* 008 - Attempting to jump to a location undefined in memory.  Terminating execution.<br>
* <p>
* <b>Date of module being installed:</b> 5/21/08
* <p><b>Original Author:</b>  Keith Hill
* @param bit_code This is the 10 digit bit code that determines the value of the operand to be processed.
* @param lit_flag This is the one digit bit code that flags if the operand is a literal or not.
* @return 1 is returned if the operation was completed successfully without errors. 3000 is returned if it runs into a memory error.  2000 is returned if the attempt is made to jump to an undefined location in memory.
*/ 
    public static int Equal(String bit_code,String lit_flag){
        int return_value =1;
        int operand = Integer.parseInt(bit_code, 2);
        
        if(Control.memory[operand].equals("x")){
            System.out.println("Error 169:  Value at memory not defined.  0 substituted.");
            operand = 0;
            return_value = 3000;
        }
        else{
            operand = Integer.parseInt(Control.memory[operand],16);
        }
        
        int top_of_stack = Stack.PopTest();
        if(top_of_stack == 0){
            if(operand >Control.max_location || operand < Control.starting_location){
                System.out.println("Error 008: Attempting to jump to a location undefined in memory.  Terminating execution.");
                Control.finished = true;
                return_value = 2000;
                return return_value;
            }
            
            Control.location_counter = operand;
        }
        else{
            Control.location_counter++;
        }
        
        return return_value;
    }
    
    
                       /**
* The Less function will be called when the function bits are 010.  The function will first get an interger value from the bit code in the operand 
     * field from the instruction. 
     * Then, the function will find the value in that memory location and use that as the operand value.  
     * The function then pops an item in the test stack.  If is 2, it will jump to the desired location.<p>
* <p>
* <b>Change Log:</b><br>
* None<br>
* <p>
* <b>Error Conditions Tested:</b><br>
* 169 - Value at memory not defined. <br>
* 008 - Attempting to jump to a location undefined in memory.  Terminating execution.<br>
* <p>
* <b>Date of module being installed:</b> 5/21/08
* <p><b>Original Author:</b>  Keith Hill
* @param bit_code This is the 10 digit bit code that determines the value of the operand to be processed.
* @param lit_flag This is the one digit bit code that flags if the operand is a literal or not.
* @return 1 is returned if the operation was completed successfully without errors. 3000 is returned if it runs into a memory error. 2000 is returned if the attempt is made to jump to an undefined location in memory.
*/ 
    public static int Less(String bit_code,String lit_flag){
        int return_value =1;
        int operand = Integer.parseInt(bit_code, 2);
        
        if(Control.memory[operand].equals("x")){
            System.out.println("Error 169:  Value at memory not defined.  0 substituted.");
            operand = 0;
            return_value = 3000;
        }
        else{
            operand = Integer.parseInt(Control.memory[operand],16);
        }
        
        int top_of_stack = Stack.PopTest();        
        
        if(top_of_stack == 2){
            if(operand >Control.max_location || operand < Control.starting_location){
                System.out.println("Error 008: Attempting to jump to a location undefined in memory.  Terminating execution.");
                Control.finished = true;
                return_value = 2000;
                return return_value;
            }
            
            Control.location_counter = operand;
        }
        else{
            Control.location_counter++;
        }
        
        return return_value;
    }
    
                         /**
* The Greater function will be called when the function bits are 011.  The function will first get an interger value from the bit code in the operand 
     * field from the instruction. 
     * Then, the function will find the value in that memory location and use that as the operand value.  
     * The function then pops an item in the test stack.  If is 3, it will jump to the desired location.<p>
* <p>
* <b>Change Log:</b><br>
* None<br>
* <p>
* <b>Error Conditions Tested:</b><br>
* 169 - Value at memory not defined. <br>
* 008 - Attempting to jump to a location undefined in memory.  Terminating execution.<br>
* <p>
* <b>Date of module being installed:</b> 5/21/08
* <p><b>Original Author:</b>  Keith Hill
* @param bit_code This is the 10 digit bit code that determines the value of the operand to be processed.
* @param lit_flag This is the one digit bit code that flags if the operand is a literal or not.
* @return 1 is returned if the operation was completed successfully without errors. 3000 is returned if it runs into a memory error. 2000 is returned if the attempt is made to jump to an undefined location in memory.
*/ 
    public static int Greater(String bit_code,String lit_flag){
        int return_value =1;
        int operand = Integer.parseInt(bit_code, 2);
        
        if(Control.memory[operand].equals("x")){
            System.out.println("Error 169:  Value at memory not defined.  0 substituted.");
            operand = 0;
            return_value = 3000;
        }
        else{
            operand = Integer.parseInt(Control.memory[operand],16);
        }
        
        int top_of_stack = Stack.PopTest();        
        
        if(top_of_stack == 3){
            if(operand >Control.max_location || operand < Control.starting_location){
                System.out.println("Error 008: Attempting to jump to a location undefined in memory.  Terminating execution.");
                Control.finished = true;
                return_value = 2000;
                return return_value;
            }
            
            Control.location_counter = operand;
        }
        else{
            Control.location_counter++;
        }
        
        return return_value;
    }
   
                             /**
* The Tnull function will be called when the function bits are 110.  The function will first get an interger value from the bit code in the operand 
     * field from the instruction. 
     * Then, the function will find the value in that memory location and use that as the operand value.  
     * The function checks the size of the test stack.  If is 0, it will jump to the desired location.<p>
* <p>
* <b>Change Log:</b><br>
* None<br>
* <p>
* <b>Error Conditions Tested:</b><br>
* 169 - Value at memory not defined. <br>
* 008 - Attempting to jump to a location undefined in memory.  Terminating execution.<br>
* <p>
* <b>Date of module being installed:</b> 5/21/08
* <p><b>Original Author:</b>  Keith Hill
* @param bit_code This is the 10 digit bit code that determines the value of the operand to be processed.
* @param lit_flag This is the one digit bit code that flags if the operand is a literal or not.
* @return 1 is returned if the operation was completed successfully without errors. 3000 is returned if it runs into a memory error. 2000 is returned if the attempt is made to jump to an undefined location in memory.
*/ 
    public static int Tnull(String bit_code,String lit_flag){
        int return_value =1;
        int operand = Integer.parseInt(bit_code, 2);
        
        if(Control.memory[operand].equals("x")){
            System.out.println("Error 169:  Value at memory not defined.  0 substituted.");
            operand = 0;
            return_value = 3000;
        }
        else{
            operand = Integer.parseInt(Control.memory[operand],16);
        }
        
        int top_of_stack = Stack.PopTest();        
        
        if(Stack.test_stack_size==0){
            if(operand >Control.max_location || operand < Control.starting_location){
                System.out.println("Error 008: Attempting to jump to a location undefined in memory.  Terminating execution.");
                Control.finished = true;
                return_value = 2000;
                return return_value;
            }            
            Control.location_counter = operand;
        }
        else{
            Control.location_counter++;
        }
        
        return return_value;
    }
    
    
                                 /**
* The Dnull function will be called when the function bits are 111.  The function will first get an interger value from the bit code in the operand 
     * field from the instruction. 
     * Then, the function will find the value in that memory location and use that as the operand value.  
     * The function checks the size of the data stack.  If is 0, it will jump to the desired location.<p>
* <p>
* <b>Change Log:</b><br>
* None<br>
* <p>
* <b>Error Conditions Tested:</b><br>
* 169 - Value at memory not defined. <br>
* 008 - Attempting to jump to a location undefined in memory.  Terminating execution.<br>
* <p>
* <b>Date of module being installed:</b> 5/21/08
* <p><b>Original Author:</b>  Keith Hill
* @param bit_code This is the 10 digit bit code that determines the value of the operand to be processed.
* @param lit_flag This is the one digit bit code that flags if the operand is a literal or not.
* @return 1 is returned if the operation was completed successfully without errors. 3000 is returned if it runs into a memory error. 2000 is returned if the attempt is made to jump to an undefined location in memory.
*/ 
    public static int Dnull(String bit_code,String lit_flag){
        int return_value =1;
        int operand = Integer.parseInt(bit_code, 2);
        
        if(Control.memory[operand].equals("x")){
            System.out.println("Error 169:  Value at memory not defined.  0 substituted.");
            operand = 0;
            return_value = 3000;
        }
        else{
            operand = Integer.parseInt(Control.memory[operand],16);
        }
        
        int top_of_stack = Stack.PopTest();        
        
        if(Stack.data_stack_size==0){
            if(operand >Control.max_location || operand < Control.starting_location){
                System.out.println("Error 008: Attempting to jump to a location undefined in memory.  Terminating execution.");
                Control.finished = true;
                return_value = 2000;
                return return_value;
            }            
            Control.location_counter = operand;
        }
        else{
            Control.location_counter++;
        }
        
        return return_value;
    }
    
             /**
    * The Control function will receive the call from the Simulator's Control class.  It will receive the bit 
         * information.  It will start by throwing away the first two bits since they are no longer needed.  It will then 
         * check the next three bits and call the appropriate function class with the literal flag and the operand bits as 
         * parameters.
    * <p>
    * <b>Change Log:</b><br>
    * None<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * None <br>
    * <p>
    * <b>Date of module being installed:</b> 5/24/08
    * <p><b>Original Author:</b>  Keith Hill
    * @param bit_code This is the incomming bit code that will be processed.
    */
    public static void Control(String bit_code){
        bit_code = bit_code.replaceFirst("10", "");
        String function = bit_code.substring(0, 3);
        bit_code = bit_code.replaceFirst(function, "");
        String lit_flag = bit_code.substring(0,1);
        bit_code = bit_code.replaceFirst(lit_flag, "");
        
        int result = 0;
        if(function.equals("000")){
            result = Equal(bit_code,lit_flag);
        }
        else if(function.equals("001")){
            System.out.println("Error 175: Invalid function bits for this set of operations.  Line ignored.");
            result = 1000;
            Control.location_counter++;
        }
        else if(function.equals("010")){
            result = Less(bit_code,lit_flag);            
        }
        else if(function.equals("011")){
            result = Greater(bit_code,lit_flag);
        }
        else if(function.equals("100")){
            System.out.println("Error 175: Invalid function bits for this set of operations.  Line ignored.");
            result = 1000;
            Control.location_counter++;
        }
        else if(function.equals("101")){
            System.out.println("Error 175: Invalid function bits for this set of operations.  Line ignored.");
            result = 1000;
            Control.location_counter++;
        }
        else if(function.equals("110")){
            result = Tnull(bit_code,lit_flag);
        }
        else if(function.equals("111")){
            result = Dnull(bit_code,lit_flag);
        }
        else{
            System.out.println("How the fuck did that happen?");
        }
        
        IceAssembly.Convert convert_instance = new IceAssembly.Convert();
        String status_result=convert_instance.getBitCode(String.valueOf(Control.location_counter), 10);
        if(result == 1){
            status_result =  "000000"+status_result;
        }
        else if(result == 1000){
            status_result = "100000"+status_result;
        }
        else if(result == 2000){
            status_result = "100001"+status_result;
        }
        else if (result == 3000){
            status_result = "000001"+status_result;
        }
        status_result = convert_instance.binaryToHex(status_result);
        while(status_result.length()<4){
            status_result = "0" + status_result;
        }
        Stack.PushStatus(status_result);
        
    }

}
